package com.yuanian.timingwheel.model.timingwheel.bucket;

import com.yuanian.timingwheel.model.task.base.BaseTask;
import com.yuanian.timingwheel.model.task.base.Task;
import com.yuanian.timingwheel.threadpool.ThreadPoolExecutorFacade;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 时间轮上的槽，队列实现
 */
public class BucketQueue implements Bucket, Serializable {

    private ConcurrentLinkedQueue<BaseTask> taskQueue;

    //任务已经被删除的taskId集合
    private Set<Long> deletedTaskIdSet;

    //任务已经被暂停的taskId集合
    private Set<Long> suspendTaskIdSet;

    //当前轮次
    private int round;

    public BucketQueue(int round) {
        this.suspendTaskIdSet = new HashSet<>();
        this.deletedTaskIdSet = new HashSet<>();
        this.round = round;
    }

    /**
     * 添加任务
     */
    public void push(BaseTask e) {
        if(this.taskQueue == null){
            this.taskQueue = new ConcurrentLinkedQueue<>();
        }
        this.taskQueue.offer(e);
        //System.out.println(this.round + "----------" +  this.taskQueue.hashCode() + "---" + this.taskQueue.size());
    }

    /**
     * 获取任务
     */
    public Task pop(){
        return isEmpty() ? null : taskQueue.poll();
    }

    public boolean isEmpty(){
        return this.taskQueue == null || this.taskQueue.isEmpty();
    }

    public void deletedTaskId(Long taskId) {
        deletedTaskIdSet.add(taskId);
    }

    public void suspendTaskId(Long taskId) {
        suspendTaskIdSet.add(taskId);
    }

    public void consumeTaskId(Long taskId) {
        suspendTaskIdSet.remove(taskId);

    }

    /**
     * 任务是否全部完成
     * @return
     */
    public boolean isCompleted() {
        if (isEmpty()) {
            return true;
        }
        for (BaseTask e : taskQueue) {
            if (!suspendTaskIdSet.contains(e.getId())) {
                return false;
            }
        }
        return true;
    }

    public boolean executeTask() {
        boolean result = true;
        int size = taskQueue.size();
        for (int i = 0; i < size; i++) {
            //弹出任务并执行
            BaseTask cur = taskQueue.poll();
            //任务没有被删除或暂停
            if (!deletedTaskIdSet.contains(cur.getId()) && !suspendTaskIdSet.contains(cur.getId())) {
                ThreadPoolExecutorFacade.getInstance().execute(cur);
            } else if (suspendTaskIdSet.contains(cur.getId())) {
                //任务有可能被恢复,先占位
                taskQueue.offer(cur);
                result = false;
            }
        }
        return result;
    }

}
